package common.fengkai.filepost.JVM;


import java.io.*;
import java.net.URLDecoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Fengkai
 * @creat 2021/12/16
 */
public class MyClassLoader extends  ClassLoader{
    private File classPathFile;

    private static Map<String, Class> clazzCacha = new ConcurrentHashMap<>();

    public MyClassLoader ( ) throws UnsupportedEncodingException {
        String path = MyClassLoader.class.getResource("").getPath();
        //中文乱码问题需要对classPath转码处理
        String classPath  = URLDecoder.decode(path, "utf-8");
        this.classPathFile = new File(classPath);
    }

    @Override
    protected Class<?> findClass (String name) throws ClassNotFoundException {
        //自定义类加载器 重写findClass方法
        return this.findClass(name, false);
    }


    protected  Class<?> findClass(String name, boolean force){
        //获取之前有没有加载过该class
         Class cls = clazzCacha.get(name);
         if (force){
             cls = null;
         }
         String className = MyClassLoader.class.getPackage().getName() + "." + name;
         if(cls == null && classPathFile != null){

             File classFile = new File(classPathFile + "\\" + name.replaceAll("\\.", "/") + ".class");

             if(classFile.exists()){
                 FileInputStream fis = null;
                 ByteArrayOutputStream bos = null;
                   try {
                    fis = new FileInputStream(classFile);
                    bos = new ByteArrayOutputStream();
                    byte[] bytes = new byte[4096];
                    int len;
                    while ((len = fis.read(bytes)) != -1){
                        bos.write(bytes, 0, len);
                    }
                       cls = defineClass(className, bos.toByteArray(), 0, bos.size());
                       clazzCacha.put(name, cls);
                   } catch(Exception e) {
                       e.printStackTrace();
                   }finally {
                        try {
                           if (fis != null){
                               fis.close();
                           }
                        } catch(Exception e) {
                            e.printStackTrace();
                        }
                          try {
                             if (bos != null){
                                 bos.close();
                             }
                          } catch(Exception e) {
                              e.printStackTrace();
                          }
                   }
             }

         }

         return clazzCacha.get(name);
    }
}
